# coding=utf-8
from threading import Lock
from uuid import uuid1

from bluepy.btle import Scanner
from flask import Flask, jsonify, render_template
from flask_jsglue import JSGlue
from flask_socketio import SocketIO, emit, send

from bracelet_sc import BraceletMainService

async_mode = 'eventlet'

app = Flask(__name__)
jsglue = JSGlue()
jsglue.init_app(app)
socketio = SocketIO(app, async_mode=async_mode)
thread_lock = Lock()
thread_pool = {}

devs_list = []


@app.route('/')
def hello():
    return render_template('index.html')


@app.route('/get_data')
def get_base_data():
    global devs_list
    return jsonify(devs_list), 200


@app.route('/scan')
def scan():
    global devs_list
    devs_list = []
    scanner = Scanner()
    devices = scanner.scan(10.0)
    for dev in devices:
        d = {}
        # print "Device %s (%s), RSSI=%d dB" % (dev.addr, dev.addrType, dev.rssi)
        d['index'] = str(uuid1())
        d['addr'] = dev.addr
        d['addrType'] = dev.addrType
        for (adtype, desc, value) in dev.getScanData():
            d[desc.replace(' ', '')] = value
        devs_list.append(d)
    return jsonify(devs_list), 200


@app.route('/main')
def main():
    return render_template('main.html')


@socketio.on('connect', namespace='/test')
def test_connect():
    print('Client connected')


@socketio.on('disconnect', namespace='/test')
def test_disconnect():
    print('Client disconnected')


@socketio.on('close', namespace='/test')
def close_bracelet(message):
    global thread_pool
    if message in thread_pool.keys():
        bracelet = thread_pool[message]
        bracelet.cycle_flag = False
    else:
        print '{} not in running'.format(message)


@socketio.on('open', namespace='/test')
def handle_message(message):
    global thread_pool, devs_list
    target = None
    print('received message: ' + message)
    for item in devs_list:
        if item['index'] == message:
            target = item
            break
    if target:
        if target['Manufacturer'].startswith('05ff55aa0fac'):
            with thread_lock:
                if 'CompleteLocalName' in target.keys() and target['CompleteLocalName'] not in thread_pool.keys():
                    emit('server_response', {'data': 'begin collect'})
                    # thread = socketio.start_background_task(reconnectNew, target['addr'], target['addrType'], socketio)
                    # thread_pool[target['CompleteLocalName']] = thread
                    print 'begin collect old bracelet'
                else:
                    emit("server_response", {'data': 'the bracelet is already connected'})
        elif 'CompleteLocalName' in target.keys() and target['CompleteLocalName'].startswith('K18S'):
            with thread_lock:
                if target['CompleteLocalName'] not in thread_pool.keys():
                    emit('server_response', {'data': u'开始收集手环数据'})
                    bracelet = BraceletMainService(target['addr'], target['addrType'], target['CompleteLocalName'])
                    bracelet.conn()
                    socketio.start_background_task(background_run, bracelet, socketio)
                    thread_pool[target['CompleteLocalName']] = bracelet
                else:
                    emit("server_response", {'data': u'手环已经连接'})
                    bracelet = thread_pool[target['CompleteLocalName']]
                    bracelet.cycle_flag = True
                    socketio.start_background_task(background_run, bracelet, socketio)

        else:
            print 'not valid deivce'
            emit('server_response', {'data': 'not valid device'})

    else:
        print 'can not find target'


@socketio.on('message')
def handle_message(message):
    send(message)


def background_run(brace, socketio):
    brace.detect(socketio)


def background_thread():
    """Example of how to send server generated events to clients."""
    count = 0
    while True:
        socketio.sleep(10)
        count += 1
        socketio.emit('server_response',
                      {'data': 'Server generated event', 'count': count},
                      namespace='/test')


if __name__ == '__main__':
    socketio.run(app, host="0.0.0.0", debug=True)
